<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Interactive Visual Debugging of Computer Vision applications</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d3/d81/tutorial_contrib_root.html">Tutorials for contrib modules</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Interactive Visual Debugging of Computer Vision applications </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>What is the most common way to debug computer vision applications? Usually the answer is temporary, hacked together, custom code that must be removed from the code for release compilation.</p>
<p>In this tutorial we will show how to use the visual debugging features of the <b>cvv</b> module (<em><a class="el" href="../../d4/d7f/cvv_8hpp.html">opencv2/cvv.hpp</a></em>) instead.</p>
<h2>Goals </h2>
<p>In this tutorial you will learn how to:</p>
<ul>
<li>Add cvv debug calls to your application</li>
<li>Use the visual debug GUI</li>
<li>Enable and disable the visual debug features during compilation (with zero runtime overhead when disabled)</li>
</ul>
<h2>Code </h2>
<p>The example code</p>
<ul>
<li>captures images (<em>videoio</em>), e.g. from a webcam,</li>
<li>applies some filters to each image (<em>imgproc</em>),</li>
<li>detects image features and matches them to the previous image (<em>features2d</em>).</li>
</ul>
<p>If the program is compiled without visual debugging (see CMakeLists.txt below) the only result is some information printed to the command line. We want to demonstrate how much debugging or development functionality is added by just a few lines of <em>cvv</em> commands.</p>
<div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno">    1</span>&#160;<span class="comment">// system includes</span></div><div class="line"><a name="l00002"></a><span class="lineno">    2</span>&#160;<span class="preprocessor">#include &lt;iostream&gt;</span></div><div class="line"><a name="l00003"></a><span class="lineno">    3</span>&#160;</div><div class="line"><a name="l00004"></a><span class="lineno">    4</span>&#160;<span class="comment">// library includes</span></div><div class="line"><a name="l00005"></a><span class="lineno">    5</span>&#160;<span class="preprocessor">#include &lt;<a class="code" href="../../d1/d4f/imgproc_2include_2opencv2_2imgproc_8hpp.html">opencv2/imgproc.hpp</a>&gt;</span></div><div class="line"><a name="l00006"></a><span class="lineno">    6</span>&#160;<span class="preprocessor">#include &lt;<a class="code" href="../../d5/d0d/features2d_8hpp.html">opencv2/features2d.hpp</a>&gt;</span></div><div class="line"><a name="l00007"></a><span class="lineno">    7</span>&#160;<span class="preprocessor">#include &lt;opencv2/imgproc/types_c.h&gt;</span></div><div class="line"><a name="l00008"></a><span class="lineno">    8</span>&#160;<span class="preprocessor">#include &lt;<a class="code" href="../../dc/d3d/videoio_8hpp.html">opencv2/videoio.hpp</a>&gt;</span></div><div class="line"><a name="l00009"></a><span class="lineno">    9</span>&#160;<span class="preprocessor">#include &lt;opencv2/videoio/videoio_c.h&gt;</span></div><div class="line"><a name="l00010"></a><span class="lineno">   10</span>&#160;</div><div class="line"><a name="l00011"></a><span class="lineno">   11</span>&#160;<span class="preprocessor">#define CVVISUAL_DEBUGMODE</span></div><div class="line"><a name="l00012"></a><span class="lineno">   12</span>&#160;<span class="preprocessor">#include &lt;<a class="code" href="../../d1/d9f/debug__mode_8hpp.html">opencv2/cvv/debug_mode.hpp</a>&gt;</span></div><div class="line"><a name="l00013"></a><span class="lineno">   13</span>&#160;<span class="preprocessor">#include &lt;<a class="code" href="../../df/d91/show__image_8hpp.html">opencv2/cvv/show_image.hpp</a>&gt;</span></div><div class="line"><a name="l00014"></a><span class="lineno">   14</span>&#160;<span class="preprocessor">#include &lt;<a class="code" href="../../d1/dd2/filter_8hpp.html">opencv2/cvv/filter.hpp</a>&gt;</span></div><div class="line"><a name="l00015"></a><span class="lineno">   15</span>&#160;<span class="preprocessor">#include &lt;<a class="code" href="../../d7/de1/dmatch_8hpp.html">opencv2/cvv/dmatch.hpp</a>&gt;</span></div><div class="line"><a name="l00016"></a><span class="lineno">   16</span>&#160;<span class="preprocessor">#include &lt;<a class="code" href="../../db/d19/final__show_8hpp.html">opencv2/cvv/final_show.hpp</a>&gt;</span></div><div class="line"><a name="l00017"></a><span class="lineno">   17</span>&#160;</div><div class="line"><a name="l00018"></a><span class="lineno">   18</span>&#160;<span class="keyword">using namespace </span>std;</div><div class="line"><a name="l00019"></a><span class="lineno">   19</span>&#160;<span class="keyword">using namespace </span><a class="code" href="../../d2/d75/namespacecv.html">cv</a>;</div><div class="line"><a name="l00020"></a><span class="lineno">   20</span>&#160;</div><div class="line"><a name="l00021"></a><span class="lineno">   21</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">class</span> T&gt; std::string <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#af971ba08e7b65ecc2b809866b98f317b">toString</a>(<span class="keyword">const</span> T&amp; p_arg)</div><div class="line"><a name="l00022"></a><span class="lineno">   22</span>&#160;{</div><div class="line"><a name="l00023"></a><span class="lineno">   23</span>&#160;  std::stringstream ss;</div><div class="line"><a name="l00024"></a><span class="lineno">   24</span>&#160;</div><div class="line"><a name="l00025"></a><span class="lineno">   25</span>&#160;  ss &lt;&lt; p_arg;</div><div class="line"><a name="l00026"></a><span class="lineno">   26</span>&#160;</div><div class="line"><a name="l00027"></a><span class="lineno">   27</span>&#160;  <span class="keywordflow">return</span> ss.str();</div><div class="line"><a name="l00028"></a><span class="lineno">   28</span>&#160;}</div><div class="line"><a name="l00029"></a><span class="lineno">   29</span>&#160;</div><div class="line"><a name="l00030"></a><span class="lineno">   30</span>&#160;</div><div class="line"><a name="l00031"></a><span class="lineno">   31</span>&#160;</div><div class="line"><a name="l00032"></a><span class="lineno">   32</span>&#160;</div><div class="line"><a name="l00033"></a><span class="lineno">   33</span>&#160;<span class="keywordtype">int</span></div><div class="line"><a name="l00034"></a><span class="lineno">   34</span>&#160;main(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span>** argv)</div><div class="line"><a name="l00035"></a><span class="lineno">   35</span>&#160;{</div><div class="line"><a name="l00036"></a><span class="lineno">   36</span>&#160;  <a class="code" href="../../d6/d50/classcv_1_1Size__.html">cv::Size</a>* resolution = <span class="keyword">nullptr</span>;</div><div class="line"><a name="l00037"></a><span class="lineno">   37</span>&#160;</div><div class="line"><a name="l00038"></a><span class="lineno">   38</span>&#160;  <span class="comment">// parser keys</span></div><div class="line"><a name="l00039"></a><span class="lineno">   39</span>&#160;  <span class="keyword">const</span> <span class="keywordtype">char</span> *keys =</div><div class="line"><a name="l00040"></a><span class="lineno">   40</span>&#160;      <span class="stringliteral">&quot;{ help h usage ?  |   | show this message }&quot;</span></div><div class="line"><a name="l00041"></a><span class="lineno">   41</span>&#160;      <span class="stringliteral">&quot;{ width W         |  0| camera resolution width. leave at 0 to use defaults }&quot;</span></div><div class="line"><a name="l00042"></a><span class="lineno">   42</span>&#160;      <span class="stringliteral">&quot;{ height H        |  0| camera resolution height. leave at 0 to use defaults }&quot;</span>;</div><div class="line"><a name="l00043"></a><span class="lineno">   43</span>&#160;</div><div class="line"><a name="l00044"></a><span class="lineno">   44</span>&#160;  <a class="code" href="../../d0/d2e/classcv_1_1CommandLineParser.html">CommandLineParser</a> parser(argc, argv, keys);</div><div class="line"><a name="l00045"></a><span class="lineno">   45</span>&#160;  <span class="keywordflow">if</span> (parser.has(<span class="stringliteral">&quot;help&quot;</span>)) {</div><div class="line"><a name="l00046"></a><span class="lineno">   46</span>&#160;    parser.printMessage();</div><div class="line"><a name="l00047"></a><span class="lineno">   47</span>&#160;    <span class="keywordflow">return</span> 0;</div><div class="line"><a name="l00048"></a><span class="lineno">   48</span>&#160;  }</div><div class="line"><a name="l00049"></a><span class="lineno">   49</span>&#160;  <span class="keywordtype">int</span> res_w = parser.get&lt;<span class="keywordtype">int</span>&gt;(<span class="stringliteral">&quot;width&quot;</span>);</div><div class="line"><a name="l00050"></a><span class="lineno">   50</span>&#160;  <span class="keywordtype">int</span> res_h = parser.get&lt;<span class="keywordtype">int</span>&gt;(<span class="stringliteral">&quot;height&quot;</span>);</div><div class="line"><a name="l00051"></a><span class="lineno">   51</span>&#160;</div><div class="line"><a name="l00052"></a><span class="lineno">   52</span>&#160;  <span class="comment">// setup video capture</span></div><div class="line"><a name="l00053"></a><span class="lineno">   53</span>&#160;  <a class="code" href="../../d8/dfe/classcv_1_1VideoCapture.html">cv::VideoCapture</a> capture(0);</div><div class="line"><a name="l00054"></a><span class="lineno">   54</span>&#160;  <span class="keywordflow">if</span> (!capture.isOpened()) {</div><div class="line"><a name="l00055"></a><span class="lineno">   55</span>&#160;    std::cout &lt;&lt; <span class="stringliteral">&quot;Could not open VideoCapture&quot;</span> &lt;&lt; std::endl;</div><div class="line"><a name="l00056"></a><span class="lineno">   56</span>&#160;    <span class="keywordflow">return</span> 1;</div><div class="line"><a name="l00057"></a><span class="lineno">   57</span>&#160;  }</div><div class="line"><a name="l00058"></a><span class="lineno">   58</span>&#160;</div><div class="line"><a name="l00059"></a><span class="lineno">   59</span>&#160;  <span class="keywordflow">if</span> (res_w&gt;0 &amp;&amp; res_h&gt;0) {</div><div class="line"><a name="l00060"></a><span class="lineno">   60</span>&#160;    printf(<span class="stringliteral">&quot;Setting resolution to %dx%d\n&quot;</span>, res_w, res_h);</div><div class="line"><a name="l00061"></a><span class="lineno">   61</span>&#160;    capture.set(CV_CAP_PROP_FRAME_WIDTH, res_w);</div><div class="line"><a name="l00062"></a><span class="lineno">   62</span>&#160;    capture.set(CV_CAP_PROP_FRAME_HEIGHT, res_h);</div><div class="line"><a name="l00063"></a><span class="lineno">   63</span>&#160;  }</div><div class="line"><a name="l00064"></a><span class="lineno">   64</span>&#160;</div><div class="line"><a name="l00065"></a><span class="lineno">   65</span>&#160;</div><div class="line"><a name="l00066"></a><span class="lineno">   66</span>&#160;  <a class="code" href="../../d3/d63/classcv_1_1Mat.html">cv::Mat</a> prevImgGray;</div><div class="line"><a name="l00067"></a><span class="lineno">   67</span>&#160;  std::vector&lt;cv::KeyPoint&gt; prevKeypoints;</div><div class="line"><a name="l00068"></a><span class="lineno">   68</span>&#160;  <a class="code" href="../../d3/d63/classcv_1_1Mat.html">cv::Mat</a> prevDescriptors;</div><div class="line"><a name="l00069"></a><span class="lineno">   69</span>&#160;</div><div class="line"><a name="l00070"></a><span class="lineno">   70</span>&#160;  <span class="keywordtype">int</span> maxFeatureCount = 500;</div><div class="line"><a name="l00071"></a><span class="lineno">   71</span>&#160;  <a class="code" href="../../dc/d84/group__core__basic.html#ga6395ca871a678020c4a31fadf7e8cc63">Ptr&lt;ORB&gt;</a> detector = ORB::create(maxFeatureCount);</div><div class="line"><a name="l00072"></a><span class="lineno">   72</span>&#160;</div><div class="line"><a name="l00073"></a><span class="lineno">   73</span>&#160;  <a class="code" href="../../d3/da1/classcv_1_1BFMatcher.html">cv::BFMatcher</a> matcher(<a class="code" href="../../d2/de8/group__core__array.html#ggad12cefbcb5291cf958a85b4b67b6149fa4b063afd04aebb8dd07085a1207da727">cv::NORM_HAMMING</a>);</div><div class="line"><a name="l00074"></a><span class="lineno">   74</span>&#160;</div><div class="line"><a name="l00075"></a><span class="lineno">   75</span>&#160;  <span class="keywordflow">for</span> (<span class="keywordtype">int</span> imgId = 0; imgId &lt; 10; imgId++) {</div><div class="line"><a name="l00076"></a><span class="lineno">   76</span>&#160;    <span class="comment">// capture a frame</span></div><div class="line"><a name="l00077"></a><span class="lineno">   77</span>&#160;    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">cv::Mat</a> imgRead;</div><div class="line"><a name="l00078"></a><span class="lineno">   78</span>&#160;    capture &gt;&gt; imgRead;</div><div class="line"><a name="l00079"></a><span class="lineno">   79</span>&#160;    printf(<span class="stringliteral">&quot;%d: image captured\n&quot;</span>, imgId);</div><div class="line"><a name="l00080"></a><span class="lineno">   80</span>&#160;</div><div class="line"><a name="l00081"></a><span class="lineno">   81</span>&#160;    std::string imgIdString{<span class="stringliteral">&quot;imgRead&quot;</span>};</div><div class="line"><a name="l00082"></a><span class="lineno">   82</span>&#160;    imgIdString += <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#af971ba08e7b65ecc2b809866b98f317b">toString</a>(imgId);</div><div class="line"><a name="l00083"></a><span class="lineno">   83</span>&#160;        <a class="code" href="../../df/dff/group__cvv.html#ga776e85265cd41bf22cfd8c5bfff1b045">cvv::showImage</a>(imgRead, <a class="code" href="../../da/da7/call__meta__data_8hpp.html#a17eec6bed7eb93ae572abf9a2b9c6799">CVVISUAL_LOCATION</a>, imgIdString.c_str());</div><div class="line"><a name="l00084"></a><span class="lineno">   84</span>&#160;</div><div class="line"><a name="l00085"></a><span class="lineno">   85</span>&#160;    <span class="comment">// convert to grayscale</span></div><div class="line"><a name="l00086"></a><span class="lineno">   86</span>&#160;    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">cv::Mat</a> imgGray;</div><div class="line"><a name="l00087"></a><span class="lineno">   87</span>&#160;    <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#ga397ae87e1288a81d2363b61574eb8cab">cv::cvtColor</a>(imgRead, imgGray, <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#gga4e0972be5de079fed4e3a10e24ef5ef0a353a4b8db9040165db4dacb5bcefb6ea">COLOR_BGR2GRAY</a>);</div><div class="line"><a name="l00088"></a><span class="lineno">   88</span>&#160;        <a class="code" href="../../df/dff/group__cvv.html#ga7fcba850f6ecb852203e5622a37c3bc6">cvv::debugFilter</a>(imgRead, imgGray, <a class="code" href="../../da/da7/call__meta__data_8hpp.html#a17eec6bed7eb93ae572abf9a2b9c6799">CVVISUAL_LOCATION</a>, <span class="stringliteral">&quot;to gray&quot;</span>);</div><div class="line"><a name="l00089"></a><span class="lineno">   89</span>&#160;</div><div class="line"><a name="l00090"></a><span class="lineno">   90</span>&#160;    <span class="comment">// detect ORB features</span></div><div class="line"><a name="l00091"></a><span class="lineno">   91</span>&#160;    std::vector&lt;cv::KeyPoint&gt; keypoints;</div><div class="line"><a name="l00092"></a><span class="lineno">   92</span>&#160;    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">cv::Mat</a> descriptors;</div><div class="line"><a name="l00093"></a><span class="lineno">   93</span>&#160;    detector-&gt;detectAndCompute(imgGray, <a class="code" href="../../dc/d84/group__core__basic.html#gad9287b23bba2fed753b36ef561ae7346">cv::noArray</a>(), keypoints, descriptors);</div><div class="line"><a name="l00094"></a><span class="lineno">   94</span>&#160;    printf(<span class="stringliteral">&quot;%d: detected %zd keypoints\n&quot;</span>, imgId, keypoints.size());</div><div class="line"><a name="l00095"></a><span class="lineno">   95</span>&#160;</div><div class="line"><a name="l00096"></a><span class="lineno">   96</span>&#160;    <span class="comment">// match them to previous image (if available)</span></div><div class="line"><a name="l00097"></a><span class="lineno">   97</span>&#160;    <span class="keywordflow">if</span> (!prevImgGray.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#abbec3525a852e77998aba034813fded4">empty</a>()) {</div><div class="line"><a name="l00098"></a><span class="lineno">   98</span>&#160;      std::vector&lt;cv::DMatch&gt; matches;</div><div class="line"><a name="l00099"></a><span class="lineno">   99</span>&#160;      matcher.match(prevDescriptors, descriptors, matches);</div><div class="line"><a name="l00100"></a><span class="lineno">  100</span>&#160;      printf(<span class="stringliteral">&quot;%d: all matches size=%zd\n&quot;</span>, imgId, matches.size());</div><div class="line"><a name="l00101"></a><span class="lineno">  101</span>&#160;      std::string allMatchIdString{<span class="stringliteral">&quot;all matches &quot;</span>};</div><div class="line"><a name="l00102"></a><span class="lineno">  102</span>&#160;      allMatchIdString += <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#af971ba08e7b65ecc2b809866b98f317b">toString</a>(imgId-1) + <span class="stringliteral">&quot;&lt;-&gt;&quot;</span> + <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#af971ba08e7b65ecc2b809866b98f317b">toString</a>(imgId);</div><div class="line"><a name="l00103"></a><span class="lineno">  103</span>&#160;      <a class="code" href="../../df/dff/group__cvv.html#ga68668c8dddd147c90070efa600c6d0ac">cvv::debugDMatch</a>(prevImgGray, prevKeypoints, imgGray, keypoints, matches, <a class="code" href="../../da/da7/call__meta__data_8hpp.html#a17eec6bed7eb93ae572abf9a2b9c6799">CVVISUAL_LOCATION</a>, allMatchIdString.c_str());</div><div class="line"><a name="l00104"></a><span class="lineno">  104</span>&#160;</div><div class="line"><a name="l00105"></a><span class="lineno">  105</span>&#160;      <span class="comment">// remove worst (as defined by match distance) bestRatio quantile</span></div><div class="line"><a name="l00106"></a><span class="lineno">  106</span>&#160;      <span class="keywordtype">double</span> bestRatio = 0.8;</div><div class="line"><a name="l00107"></a><span class="lineno">  107</span>&#160;      <a class="code" href="../../d2/de8/group__core__array.html#ga45dd56da289494ce874be2324856898f">std::sort</a>(matches.begin(), matches.end());</div><div class="line"><a name="l00108"></a><span class="lineno">  108</span>&#160;      matches.resize(<span class="keywordtype">int</span>(bestRatio * matches.size()));</div><div class="line"><a name="l00109"></a><span class="lineno">  109</span>&#160;      printf(<span class="stringliteral">&quot;%d: best matches size=%zd\n&quot;</span>, imgId, matches.size());</div><div class="line"><a name="l00110"></a><span class="lineno">  110</span>&#160;      std::string bestMatchIdString{<span class="stringliteral">&quot;best &quot;</span> + <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#af971ba08e7b65ecc2b809866b98f317b">toString</a>(bestRatio) + <span class="stringliteral">&quot; matches &quot;</span>};</div><div class="line"><a name="l00111"></a><span class="lineno">  111</span>&#160;      bestMatchIdString += <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#af971ba08e7b65ecc2b809866b98f317b">toString</a>(imgId-1) + <span class="stringliteral">&quot;&lt;-&gt;&quot;</span> + <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#af971ba08e7b65ecc2b809866b98f317b">toString</a>(imgId);</div><div class="line"><a name="l00112"></a><span class="lineno">  112</span>&#160;      <a class="code" href="../../df/dff/group__cvv.html#ga68668c8dddd147c90070efa600c6d0ac">cvv::debugDMatch</a>(prevImgGray, prevKeypoints, imgGray, keypoints, matches, <a class="code" href="../../da/da7/call__meta__data_8hpp.html#a17eec6bed7eb93ae572abf9a2b9c6799">CVVISUAL_LOCATION</a>, bestMatchIdString.c_str());</div><div class="line"><a name="l00113"></a><span class="lineno">  113</span>&#160;    }</div><div class="line"><a name="l00114"></a><span class="lineno">  114</span>&#160;</div><div class="line"><a name="l00115"></a><span class="lineno">  115</span>&#160;    prevImgGray = imgGray;</div><div class="line"><a name="l00116"></a><span class="lineno">  116</span>&#160;    prevKeypoints = keypoints;</div><div class="line"><a name="l00117"></a><span class="lineno">  117</span>&#160;    prevDescriptors = descriptors;</div><div class="line"><a name="l00118"></a><span class="lineno">  118</span>&#160;  }</div><div class="line"><a name="l00119"></a><span class="lineno">  119</span>&#160;</div><div class="line"><a name="l00120"></a><span class="lineno">  120</span>&#160;  <a class="code" href="../../df/dff/group__cvv.html#ga06724816aad0970637457645ae60c8ca">cvv::finalShow</a>();</div><div class="line"><a name="l00121"></a><span class="lineno">  121</span>&#160;</div><div class="line"><a name="l00122"></a><span class="lineno">  122</span>&#160;  <span class="keywordflow">return</span> 0;</div><div class="line"><a name="l00123"></a><span class="lineno">  123</span>&#160;}</div><div class="ttc" id="group__core__array_html_ga45dd56da289494ce874be2324856898f"><div class="ttname"><a href="../../d2/de8/group__core__array.html#ga45dd56da289494ce874be2324856898f">cv::sort</a></div><div class="ttdeci">void sort(InputArray src, OutputArray dst, int flags)</div><div class="ttdoc">Sorts each row or each column of a matrix. </div></div>
<div class="ttc" id="videoio_8hpp_html"><div class="ttname"><a href="../../dc/d3d/videoio_8hpp.html">videoio.hpp</a></div></div>
<div class="ttc" id="group__imgproc__color__conversions_html_gga4e0972be5de079fed4e3a10e24ef5ef0a353a4b8db9040165db4dacb5bcefb6ea"><div class="ttname"><a href="../../d8/d01/group__imgproc__color__conversions.html#gga4e0972be5de079fed4e3a10e24ef5ef0a353a4b8db9040165db4dacb5bcefb6ea">cv::COLOR_BGR2GRAY</a></div><div class="ttdoc">convert between RGB/BGR and grayscale, color conversions </div><div class="ttdef"><b>Definition:</b> imgproc.hpp:551</div></div>
<div class="ttc" id="group__core__array_html_ggad12cefbcb5291cf958a85b4b67b6149fa4b063afd04aebb8dd07085a1207da727"><div class="ttname"><a href="../../d2/de8/group__core__array.html#ggad12cefbcb5291cf958a85b4b67b6149fa4b063afd04aebb8dd07085a1207da727">cv::NORM_HAMMING</a></div><div class="ttdef"><b>Definition:</b> base.hpp:199</div></div>
<div class="ttc" id="features2d_8hpp_html"><div class="ttname"><a href="../../d5/d0d/features2d_8hpp.html">features2d.hpp</a></div></div>
<div class="ttc" id="group__core__basic_html_ga6395ca871a678020c4a31fadf7e8cc63"><div class="ttname"><a href="../../dc/d84/group__core__basic.html#ga6395ca871a678020c4a31fadf7e8cc63">cv::Ptr</a></div><div class="ttdeci">std::shared_ptr&lt; _Tp &gt; Ptr</div><div class="ttdef"><b>Definition:</b> cvstd_wrapper.hpp:23</div></div>
<div class="ttc" id="show__image_8hpp_html"><div class="ttname"><a href="../../df/d91/show__image_8hpp.html">show_image.hpp</a></div></div>
<div class="ttc" id="namespacecv_html"><div class="ttname"><a href="../../d2/d75/namespacecv.html">cv</a></div><div class="ttdoc">&quot;black box&quot; representation of the file storage associated with a file on disk. </div><div class="ttdef"><b>Definition:</b> affine.hpp:51</div></div>
<div class="ttc" id="group__cvv_html_ga776e85265cd41bf22cfd8c5bfff1b045"><div class="ttname"><a href="../../df/dff/group__cvv.html#ga776e85265cd41bf22cfd8c5bfff1b045">cvv::showImage</a></div><div class="ttdeci">static void showImage(cv::InputArray img, impl::CallMetaData metaData=impl::CallMetaData(), const char *description=nullptr, const char *view=nullptr)</div><div class="ttdoc">Add a single image to debug GUI (similar to imshow &lt;&gt;). </div><div class="ttdef"><b>Definition:</b> show_image.hpp:38</div></div>
<div class="ttc" id="classcv_1_1CommandLineParser_html"><div class="ttname"><a href="../../d0/d2e/classcv_1_1CommandLineParser.html">cv::CommandLineParser</a></div><div class="ttdoc">Designed for command line parsing. </div><div class="ttdef"><b>Definition:</b> utility.hpp:799</div></div>
<div class="ttc" id="classcv_1_1VideoCapture_html"><div class="ttname"><a href="../../d8/dfe/classcv_1_1VideoCapture.html">cv::VideoCapture</a></div><div class="ttdoc">Class for video capturing from video files, image sequences or cameras. </div><div class="ttdef"><b>Definition:</b> videoio.hpp:664</div></div>
<div class="ttc" id="group__imgproc__color__conversions_html_ga397ae87e1288a81d2363b61574eb8cab"><div class="ttname"><a href="../../d8/d01/group__imgproc__color__conversions.html#ga397ae87e1288a81d2363b61574eb8cab">cv::cvtColor</a></div><div class="ttdeci">void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0)</div><div class="ttdoc">Converts an image from one color space to another. </div></div>
<div class="ttc" id="classcv_1_1Size___html"><div class="ttname"><a href="../../d6/d50/classcv_1_1Size__.html">cv::Size_</a></div><div class="ttdoc">Template class for specifying the size of an image or rectangle. </div><div class="ttdef"><b>Definition:</b> types.hpp:315</div></div>
<div class="ttc" id="group__cvv_html_ga06724816aad0970637457645ae60c8ca"><div class="ttname"><a href="../../df/dff/group__cvv.html#ga06724816aad0970637457645ae60c8ca">cvv::finalShow</a></div><div class="ttdeci">void finalShow()</div><div class="ttdoc">Passes the control to the debug-window for a last time. </div><div class="ttdef"><b>Definition:</b> final_show.hpp:23</div></div>
<div class="ttc" id="namespacecv_1_1dnn_html_af971ba08e7b65ecc2b809866b98f317b"><div class="ttname"><a href="../../df/d57/namespacecv_1_1dnn.html#af971ba08e7b65ecc2b809866b98f317b">cv::dnn::toString</a></div><div class="ttdeci">static std::string toString(const MatShape &amp;shape, const String &amp;name=&quot;&quot;)</div><div class="ttdef"><b>Definition:</b> shape_utils.hpp:187</div></div>
<div class="ttc" id="classcv_1_1BFMatcher_html"><div class="ttname"><a href="../../d3/da1/classcv_1_1BFMatcher.html">cv::BFMatcher</a></div><div class="ttdoc">Brute-force descriptor matcher. </div><div class="ttdef"><b>Definition:</b> features2d.hpp:1199</div></div>
<div class="ttc" id="group__core__basic_html_gad9287b23bba2fed753b36ef561ae7346"><div class="ttname"><a href="../../dc/d84/group__core__basic.html#gad9287b23bba2fed753b36ef561ae7346">cv::noArray</a></div><div class="ttdeci">InputOutputArray noArray()</div></div>
<div class="ttc" id="group__cvv_html_ga7fcba850f6ecb852203e5622a37c3bc6"><div class="ttname"><a href="../../df/dff/group__cvv.html#ga7fcba850f6ecb852203e5622a37c3bc6">cvv::debugFilter</a></div><div class="ttdeci">static void debugFilter(cv::InputArray original, cv::InputArray result, impl::CallMetaData metaData=impl::CallMetaData(), const char *description=nullptr, const char *view=nullptr)</div><div class="ttdoc">Use the debug-framework to compare two images (from which the second is intended to be the result of ...</div><div class="ttdef"><b>Definition:</b> filter.hpp:36</div></div>
<div class="ttc" id="group__cvv_html_ga68668c8dddd147c90070efa600c6d0ac"><div class="ttname"><a href="../../df/dff/group__cvv.html#ga68668c8dddd147c90070efa600c6d0ac">cvv::debugDMatch</a></div><div class="ttdeci">static void debugDMatch(cv::InputArray img1, std::vector&lt; cv::KeyPoint &gt; keypoints1, cv::InputArray img2, std::vector&lt; cv::KeyPoint &gt; keypoints2, std::vector&lt; cv::DMatch &gt; matches, const impl::CallMetaData &amp;data, const char *description=nullptr, const char *view=nullptr, bool useTrainDescriptor=true)</div><div class="ttdoc">Add a filled in DMatch &lt;dmatch&gt; to debug GUI. </div><div class="ttdef"><b>Definition:</b> dmatch.hpp:49</div></div>
<div class="ttc" id="final__show_8hpp_html"><div class="ttname"><a href="../../db/d19/final__show_8hpp.html">final_show.hpp</a></div></div>
<div class="ttc" id="imgproc_2include_2opencv2_2imgproc_8hpp_html"><div class="ttname"><a href="../../d1/d4f/imgproc_2include_2opencv2_2imgproc_8hpp.html">imgproc.hpp</a></div></div>
<div class="ttc" id="classcv_1_1Mat_html"><div class="ttname"><a href="../../d3/d63/classcv_1_1Mat.html">cv::Mat</a></div><div class="ttdoc">n-dimensional dense array class </div><div class="ttdef"><b>Definition:</b> mat.hpp:801</div></div>
<div class="ttc" id="debug__mode_8hpp_html"><div class="ttname"><a href="../../d1/d9f/debug__mode_8hpp.html">debug_mode.hpp</a></div></div>
<div class="ttc" id="call__meta__data_8hpp_html_a17eec6bed7eb93ae572abf9a2b9c6799"><div class="ttname"><a href="../../da/da7/call__meta__data_8hpp.html#a17eec6bed7eb93ae572abf9a2b9c6799">CVVISUAL_LOCATION</a></div><div class="ttdeci">#define CVVISUAL_LOCATION</div><div class="ttdoc">Creates an instance of CallMetaData with the location of the macro as value. </div><div class="ttdef"><b>Definition:</b> call_meta_data.hpp:65</div></div>
<div class="ttc" id="dmatch_8hpp_html"><div class="ttname"><a href="../../d7/de1/dmatch_8hpp.html">dmatch.hpp</a></div></div>
<div class="ttc" id="classcv_1_1Mat_html_abbec3525a852e77998aba034813fded4"><div class="ttname"><a href="../../d3/d63/classcv_1_1Mat.html#abbec3525a852e77998aba034813fded4">cv::Mat::empty</a></div><div class="ttdeci">bool empty() const</div><div class="ttdoc">Returns true if the array has no elements. </div></div>
<div class="ttc" id="filter_8hpp_html"><div class="ttname"><a href="../../d1/dd2/filter_8hpp.html">filter.hpp</a></div></div>
</div><!-- fragment --><div class="fragment"><div class="line">cmake_minimum_required(VERSION 2.8)</div><div class="line"></div><div class="line">project(cvvisual_test)</div><div class="line"></div><div class="line">SET(CMAKE_PREFIX_PATH ~/software/opencv/install)</div><div class="line"></div><div class="line">SET(CMAKE_CXX_COMPILER &quot;g++-4.8&quot;)</div><div class="line">SET(CMAKE_CXX_FLAGS &quot;-std=c++11 -O2 -pthread -Wall -Werror&quot;)</div><div class="line"></div><div class="line"># (un)set: cmake -DCVV_DEBUG_MODE=OFF ..</div><div class="line">OPTION(CVV_DEBUG_MODE &quot;cvvisual-debug-mode&quot; ON)</div><div class="line">if(CVV_DEBUG_MODE MATCHES ON)</div><div class="line">  set(CMAKE_CXX_FLAGS &quot;${CMAKE_CXX_FLAGS} -DCVVISUAL_DEBUGMODE&quot;)</div><div class="line">endif()</div><div class="line"></div><div class="line"></div><div class="line">FIND_PACKAGE(OpenCV REQUIRED)</div><div class="line">include_directories(${OpenCV_INCLUDE_DIRS})</div><div class="line"></div><div class="line">add_executable(cvvt main.cpp)</div><div class="line">target_link_libraries(cvvt</div><div class="line">  opencv_core opencv_videoio opencv_imgproc opencv_features2d</div><div class="line">  opencv_cvv</div><div class="line">)</div></div><!-- fragment --><h2>Explanation </h2>
<ol type="1">
<li>We compile the program either using the above CmakeLists.txt with Option <em>CVV_DEBUG_MODE=ON</em> (<em>cmake -DCVV_DEBUG_MODE=ON</em>) or by adding the corresponding define <em>CVVISUAL_DEBUGMODE</em> to our compiler (e.g. <em>g++ -DCVVISUAL_DEBUGMODE</em>).</li>
<li><p class="startli">The first cvv call simply shows the image (similar to <em>imshow</em>) with the imgIdString as comment. </p><div class="fragment"><div class="line"><a class="code" href="../../df/dff/group__cvv.html#ga776e85265cd41bf22cfd8c5bfff1b045">cvv::showImage</a>(imgRead, <a class="code" href="../../da/da7/call__meta__data_8hpp.html#a17eec6bed7eb93ae572abf9a2b9c6799">CVVISUAL_LOCATION</a>, imgIdString.c_str());</div></div><!-- fragment --><p> The image is added to the overview tab in the visual debug GUI and the cvv call blocks.</p>
<div class="image">
<img src="../../01_overview_single.jpg" alt="01_overview_single.jpg"/>
<div class="caption">
image</div></div>
<p> The image can then be selected and viewed</p>
<div class="image">
<img src="../../02_single_image_view.jpg" alt="02_single_image_view.jpg"/>
<div class="caption">
image</div></div>
<p> Whenever you want to continue in the code, i.e. unblock the cvv call, you can either continue until the next cvv call (<em>Step</em>), continue until the last cvv call (*&gt;&gt;*) or run the application until it exists (<em>Close</em>).</p>
<p class="startli">We decide to press the green <em>Step</em> button.</p>
</li>
<li><p class="startli">The next cvv calls are used to debug all kinds of filter operations, i.e. operations that take a picture as input and return a picture as output. </p><div class="fragment"><div class="line"><a class="code" href="../../df/dff/group__cvv.html#ga7fcba850f6ecb852203e5622a37c3bc6">cvv::debugFilter</a>(imgRead, imgGray, <a class="code" href="../../da/da7/call__meta__data_8hpp.html#a17eec6bed7eb93ae572abf9a2b9c6799">CVVISUAL_LOCATION</a>, <span class="stringliteral">&quot;to gray&quot;</span>);</div></div><!-- fragment --><p> As with every cvv call, you first end up in the overview.</p>
<div class="image">
<img src="../../03_overview_two.jpg" alt="03_overview_two.jpg"/>
<div class="caption">
image</div></div>
<p> We decide not to care about the conversion to gray scale and press <em>Step</em>. </p><div class="fragment"><div class="line"><a class="code" href="../../df/dff/group__cvv.html#ga7fcba850f6ecb852203e5622a37c3bc6">cvv::debugFilter</a>(imgGray, imgGraySmooth, <a class="code" href="../../da/da7/call__meta__data_8hpp.html#a17eec6bed7eb93ae572abf9a2b9c6799">CVVISUAL_LOCATION</a>, <span class="stringliteral">&quot;smoothed&quot;</span>);</div></div><!-- fragment --><p> If you open the filter call, you will end up in the so called "DefaultFilterView". Both images are shown next to each other and you can (synchronized) zoom into them.</p>
<div class="image">
<img src="../../04_default_filter_view.jpg" alt="04_default_filter_view.jpg"/>
<div class="caption">
image</div></div>
<p> When you go to very high zoom levels, each pixel is annotated with its numeric values.</p>
<div class="image">
<img src="../../05_default_filter_view_high_zoom.jpg" alt="05_default_filter_view_high_zoom.jpg"/>
<div class="caption">
image</div></div>
<p> We press <em>Step</em> twice and have a look at the dilated image. </p><div class="fragment"><div class="line"><a class="code" href="../../df/dff/group__cvv.html#ga7fcba850f6ecb852203e5622a37c3bc6">cvv::debugFilter</a>(imgEdges, imgEdgesDilated, <a class="code" href="../../da/da7/call__meta__data_8hpp.html#a17eec6bed7eb93ae572abf9a2b9c6799">CVVISUAL_LOCATION</a>, <span class="stringliteral">&quot;dilated edges&quot;</span>);</div></div><!-- fragment --><p> The DefaultFilterView showing both images</p>
<div class="image">
<img src="../../06_default_filter_view_edges.jpg" alt="06_default_filter_view_edges.jpg"/>
<div class="caption">
image</div></div>
<p> Now we use the <em>View</em> selector in the top right and select the "DualFilterView". We select "Changed Pixels" as filter and apply it (middle image).</p>
<div class="image">
<img src="../../07_dual_filter_view_edges.jpg" alt="07_dual_filter_view_edges.jpg"/>
<div class="caption">
image</div></div>
<p> After we had a close look at these images, perhaps using different views, filters or other GUI features, we decide to let the program run through. Therefore we press the yellow *&gt;&gt;* button.</p>
<p class="startli">The program will block at </p><div class="fragment"><div class="line"><a class="code" href="../../df/dff/group__cvv.html#ga06724816aad0970637457645ae60c8ca">cvv::finalShow</a>();</div></div><!-- fragment --><p> and display the overview with everything that was passed to cvv in the meantime.</p>
<div class="image">
<img src="../../08_overview_all.jpg" alt="08_overview_all.jpg"/>
<div class="caption">
image</div></div>
</li>
<li><p class="startli">The cvv debugDMatch call is used in a situation where there are two images each with a set of descriptors that are matched to each other.</p>
<p class="startli">We pass both images, both sets of keypoints and their matching to the visual debug module. </p><div class="fragment"><div class="line"><a class="code" href="../../df/dff/group__cvv.html#ga68668c8dddd147c90070efa600c6d0ac">cvv::debugDMatch</a>(prevImgGray, prevKeypoints, imgGray, keypoints, matches, <a class="code" href="../../da/da7/call__meta__data_8hpp.html#a17eec6bed7eb93ae572abf9a2b9c6799">CVVISUAL_LOCATION</a>, allMatchIdString.c_str());</div></div><!-- fragment --><p> Since we want to have a look at matches, we use the filter capabilities (*#type match*) in the overview to only show match calls.</p>
<div class="image">
<img src="../../09_overview_filtered_type_match.jpg" alt="09_overview_filtered_type_match.jpg"/>
<div class="caption">
image</div></div>
<p> We want to have a closer look at one of them, e.g. to tune our parameters that use the matching. The view has various settings how to display keypoints and matches. Furthermore, there is a mouseover tooltip.</p>
<div class="image">
<img src="../../10_line_match_view.jpg" alt="10_line_match_view.jpg"/>
<div class="caption">
image</div></div>
<p> We see (visual debugging!) that there are many bad matches. We decide that only 70% of the matches should be shown - those 70% with the lowest match distance.</p>
<div class="image">
<img src="../../11_line_match_view_portion_selector.jpg" alt="11_line_match_view_portion_selector.jpg"/>
<div class="caption">
image</div></div>
<p> Having successfully reduced the visual distraction, we want to see more clearly what changed between the two images. We select the "TranslationMatchView" that shows to where the keypoint was matched in a different way.</p>
<div class="image">
<img src="../../12_translation_match_view_portion_selector.jpg" alt="12_translation_match_view_portion_selector.jpg"/>
<div class="caption">
image</div></div>
<p> It is easy to see that the cup was moved to the left during the two images.</p>
<p class="startli">Although, cvv is all about interactively <em>seeing</em> the computer vision bugs, this is complemented by a "RawView" that allows to have a look at the underlying numeric data.</p>
<div class="image">
<img src="../../13_raw_view.jpg" alt="13_raw_view.jpg"/>
<div class="caption">
image</div></div>
</li>
<li><p class="startli">There are many more useful features contained in the cvv GUI. For instance, one can group the overview tab.</p>
<div class="image">
<img src="../../14_overview_group_by_line.jpg" alt="14_overview_group_by_line.jpg"/>
<div class="caption">
image</div></div>
 <h2>Result </h2>
</li>
</ol>
<ul>
<li>By adding a view expressive lines to our computer vision program we can interactively debug it through different visualizations.</li>
<li>Once we are done developing/debugging we do not have to remove those lines. We simply disable cvv debugging (<em>cmake -DCVV_DEBUG_MODE=OFF</em> or g++ without <em>-DCVVISUAL_DEBUGMODE</em>) and our programs runs without any debug overhead.</li>
</ul>
<p>Enjoy computer vision! </p>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:38 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
